home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / Tcl / pdapilot.c < prev    next >
C/C++ Source or Header  |  1997-08-03  |  35KB  |  1,260 lines

  1.  
  2. /*
  3.  * Portions of this file are copied or derivered from various files in the
  4.  * tcl8.0b1 distribution. 
  5.  * Those portions are Copyright (c) 1995 Sun Microsystems, Inc.
  6.  *
  7.  * See the file "license.terms" for information on usage and redistribution
  8.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  9.  */
  10.  
  11. /* The remainder of this file is Copyright (c) 1997, Kenneth Albanowski, and
  12.  * is free software, licensed under the GNU Public License V2.  See the file
  13.  * COPYING for details.
  14.  */
  15.  
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <tcl.h>
  19. #include <pi-source.h>
  20. #include <pi-socket.h>
  21. #include <pi-dlp.h>
  22. #include <pi-memo.h>
  23.  
  24. #if TCL_MAJOR_VERSION >= 8
  25. # define Objects
  26. #endif
  27.  
  28. struct tcl_e {char *name; long value;};
  29.  
  30. char buf[0xffff];
  31.  
  32. static struct tcl_e domains[] = {
  33.     {"PI_AF_SLP", PI_AF_SLP},
  34.     {"AF_SLP", PI_AF_SLP},
  35.     {"SLP", PI_AF_SLP},
  36.     {0,0}};
  37. static struct tcl_e protocols[] = {
  38.     {"PI_PF_SLP", PI_PF_SLP}, 
  39.     {"PI_PF_PADP", PI_PF_PADP},
  40.     {"PI_PF_LOOP", PI_PF_LOOP},
  41.     {"PF_SLP", PI_PF_SLP}, 
  42.     {"PF_PADP", PI_PF_PADP},
  43.     {"PF_LOOP", PI_PF_LOOP},
  44.     {"SLP", PI_PF_SLP}, 
  45.     {"PADP", PI_PF_PADP},
  46.     {"LOOP", PI_PF_LOOP},
  47.     {0,0}};
  48. static struct tcl_e types[] = {
  49.     {"PI_SOCK_STREAM", PI_SOCK_STREAM},
  50.     {"PI_SOCK_DGRAM", PI_SOCK_DGRAM},
  51.     {"PI_SOCK_RAW", PI_SOCK_RAW},
  52.     {"PI_SOCK_SEQPACKET", PI_SOCK_SEQPACKET},
  53.     {"SOCK_STREAM", PI_SOCK_STREAM},
  54.     {"SOCK_DGRAM", PI_SOCK_DGRAM},
  55.     {"SOCK_RAW", PI_SOCK_RAW},
  56.     {"SOCK_SEQPACKET", PI_SOCK_SEQPACKET},
  57.     {"STREAM", PI_SOCK_STREAM},
  58.     {"DGRAM", PI_SOCK_DGRAM},
  59.     {"RAW", PI_SOCK_RAW},
  60.     {"SEQPACKET", PI_SOCK_SEQPACKET},
  61.     {0,0}};
  62.  
  63. static int
  64. PisockCloseProc(ClientData instanceData, Tcl_Interp* interp);
  65. static int
  66. PisockInputProc(ClientData instanceData, char *buf, int bufSize, int *errorCodePtr);
  67. static int
  68. PisockOutputProc(ClientData instanceData, char *buf, int toWrite, int *errorCodePtr);
  69. static void
  70. PisockWatchProc(ClientData instanceData, int mask);
  71. #if TCL_MAJOR_VERSION >=8
  72. static int
  73. PisockGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr);
  74. #else
  75. static Tcl_File
  76. OldPisockGetHandleProc(ClientData instanceData, int direction);
  77. static int
  78. PisockReadyProc(ClientData instanceData, int mask);
  79. #endif
  80.  
  81. static Tcl_ChannelType pisockChannelType = {
  82.     "pisock",                              /* Type name. */
  83.     NULL/*PisockBlockModeProc*/,                   /* Set blocking/nonblocking mode.*/
  84.     PisockCloseProc,                       /* Close proc. */
  85.     PisockInputProc,                       /* Input proc. */
  86.     PisockOutputProc,                      /* Output proc. */
  87.     NULL,                               /* Seek proc. */
  88.     NULL,                               /* Set option proc. */
  89.     NULL,                   /* Get option proc. */
  90.     PisockWatchProc,                       /* Initialize notifier. */
  91. #if TCL_MAJOR_VERSION < 8
  92.     PisockReadyProc,
  93.     OldPisockGetHandleProc,                   /* Get OS handles out of channel. */
  94. #else
  95.     PisockGetHandleProc,                   /* Get OS handles out of channel. */
  96. #endif    
  97. };
  98.  
  99.  
  100. typedef void (Tcl_PisockAcceptProc)(ClientData,Tcl_Channel);
  101.  
  102.  
  103. typedef struct PisockState {
  104.     Tcl_Channel channel;        /* Channel associated with this file. */
  105.     int fd;                     /* The socket itself. */
  106.     int flags;                  /* ORed combination of the bitfields
  107.                                  * defined below. */
  108.  
  109.     Tcl_PisockAcceptProc *acceptProc;
  110.                                     /* Proc to call on accept. */
  111.     ClientData acceptProcData;  /* The data for the accept proc. */
  112. } PisockState;
  113.  
  114. #define TCP_ASYNC_SOCKET        (1<<0)  /* Asynchronous socket. */
  115. #define TCP_ASYNC_CONNECT       (1<<1)  /* Async connect in progress. */
  116.  
  117. static int
  118. WaitForConnect(PisockState * statePtr, int * errorCodePtr);
  119.  
  120. typedef struct AcceptCallback {
  121.     char *script;                       /* Script to invoke. */
  122.     Tcl_Interp *interp;                 /* Interpreter in which to run it. */
  123. } AcceptCallback;
  124.  
  125. typedef  int (*packcmd) _ANSI_ARGS_((Tcl_Interp*, char*, char *, int));
  126. typedef  void (*unpackcmd) _ANSI_ARGS_((Tcl_Interp*, char*, int));
  127.  
  128. struct Packer {
  129.     char *name;
  130.     packcmd pack, packai, packsi;
  131.     unpackcmd unpack, unpackai, unpacksi;
  132. };
  133.  
  134. void MemoUnpackCmd(Tcl_Interp * interp, char * buf, int len)
  135. {
  136.     struct Memo m;
  137.     
  138.     len = unpack_Memo(&m, buf, len);
  139.  
  140.     Tcl_AppendElement(interp, m.text);
  141.     free_Memo(&m);
  142.  
  143. }
  144.  
  145. int MemoPackCmd(Tcl_Interp * interp, char * rec, char * buf, int len)
  146. {
  147.     struct Memo m;
  148.     
  149.     m.text = rec;
  150.     
  151.     return pack_Memo(&m, buf, len);
  152. }
  153.  
  154. struct { char * name; packcmd pack, packai, packsi; unpackcmd unpack, unpackai, unpacksi; }
  155.     DBPackers[] = {
  156.     { "MemoDB", MemoPackCmd,0,0,MemoUnpackCmd,0,0},
  157.     { 0, 0,0,0,0,0,0},
  158. };
  159.  
  160. struct Packer * pack = 0;
  161. int packers = 0;
  162.  
  163. void register_sock(int sock) {
  164.     int i;
  165.     if (packers==0) {
  166.         packers = sock+5;
  167.         pack = malloc(sizeof(struct Packer)*packers);
  168.         for(i=0;i<packers;i++) {
  169.             memset((void*)&pack[i], 0, sizeof(struct Packer));
  170.         }
  171.     } else if (sock >= packers) {
  172.         packers = sock+10;
  173.         pack = realloc(pack, sizeof(struct Packer)*packers);
  174.         for(i=sock;i<packers;i++) {
  175.             memset((void*)&pack[i], 0, sizeof(struct Packer));
  176.         }
  177.     }
  178.     memset((void*)&pack[sock], 0, sizeof(struct Packer));
  179. }
  180.  
  181. #if TCL_MAJOR_VERSION < 8
  182. # define statePtr_fd Tcl_GetFile((ClientData)statePtr->fd, TCL_UNIX_FD)
  183. #else
  184. # define statePtr_fd statePtr->fd
  185. #endif
  186.  
  187. static void     AcceptCallbackProc _ANSI_ARGS_((ClientData callbackData,
  188.                     Tcl_Channel chan));
  189. static void     RegisterPisockServerInterpCleanup _ANSI_ARGS_((Tcl_Interp *interp,
  190.                     AcceptCallback *acceptCallbackPtr));
  191. static void     PisockAcceptCallbacksDeleteProc _ANSI_ARGS_((
  192.                     ClientData clientData, Tcl_Interp *interp));
  193. static void     PisockServerCloseProc _ANSI_ARGS_((ClientData callbackData));
  194. static void     UnregisterPisockServerInterpCleanupProc _ANSI_ARGS_((
  195.                     Tcl_Interp *interp, AcceptCallback *acceptCallbackPtr));
  196.  
  197.  
  198. void
  199. Tcl_AppendInt(Tcl_Interp * interp, int result)
  200. {
  201.     char buffer[20];
  202.     sprintf(buffer, "%d", result);
  203.     Tcl_AppendElement(interp, buffer);
  204. }
  205.  
  206.         /* ARGSUSED */
  207. static void
  208. PisockAcceptCallbacksDeleteProc(clientData, interp)
  209.     ClientData clientData;      /* Data which was passed when the assocdata
  210.                                  * was registered. */
  211.     Tcl_Interp *interp;         /* Interpreter being deleted - not used. */
  212. {
  213.     Tcl_HashTable *hTblPtr;
  214.     Tcl_HashEntry *hPtr;
  215.     Tcl_HashSearch hSearch;
  216.     AcceptCallback *acceptCallbackPtr;
  217.  
  218.     hTblPtr = (Tcl_HashTable *) clientData;
  219.     for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
  220.              hPtr != (Tcl_HashEntry *) NULL;
  221.              hPtr = Tcl_NextHashEntry(&hSearch)) {
  222.         acceptCallbackPtr = (AcceptCallback *) Tcl_GetHashValue(hPtr);
  223.         acceptCallbackPtr->interp = (Tcl_Interp *) NULL;
  224.     }
  225.     Tcl_DeleteHashTable(hTblPtr);
  226.     ckfree((char *) hTblPtr);
  227. }
  228.  
  229. static void
  230. RegisterPisockServerInterpCleanup(interp, acceptCallbackPtr)
  231.     Tcl_Interp *interp;         /* Interpreter for which we want to be
  232.                                  * informed of deletion. */
  233.     AcceptCallback *acceptCallbackPtr;
  234.                                 /* The accept callback record whose
  235.                                  * interp field we want set to NULL when
  236.                                  * the interpreter is deleted. */
  237. {
  238.     Tcl_HashTable *hTblPtr;     /* Hash table for accept callback
  239.                                  * records to smash when the interpreter
  240.                                  * will be deleted. */
  241.     Tcl_HashEntry *hPtr;        /* Entry for this record. */
  242.     int new;                    /* Is the entry new? */
  243.  
  244.     hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,
  245.             "pisockAcceptCallbacks",
  246.             NULL);
  247.     if (hTblPtr == (Tcl_HashTable *) NULL) {
  248.         hTblPtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable));
  249.         Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS);
  250.         (void) Tcl_SetAssocData(interp, "pisockAcceptCallbacks",
  251.                 PisockAcceptCallbacksDeleteProc, (ClientData) hTblPtr);
  252.     }
  253.     hPtr = Tcl_CreateHashEntry(hTblPtr, (char *) acceptCallbackPtr, &new);
  254.     if (!new) {
  255.         fprintf(stderr,"RegisterPisockServerCleanup: damaged accept record table");
  256.         abort();
  257.     }
  258.     Tcl_SetHashValue(hPtr, (ClientData) acceptCallbackPtr);
  259. }
  260.  
  261. static void
  262. UnregisterPisockServerInterpCleanupProc(interp, acceptCallbackPtr)
  263.     Tcl_Interp *interp;         /* Interpreter in which the accept callback
  264.                                  * record was registered. */
  265.     AcceptCallback *acceptCallbackPtr;
  266.                                 /* The record for which to delete the
  267.                                  * registration. */
  268. {
  269.     Tcl_HashTable *hTblPtr;
  270.     Tcl_HashEntry *hPtr;
  271.  
  272.     hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,
  273.             "pisockAcceptCallbacks", NULL);
  274.     if (hTblPtr == (Tcl_HashTable *) NULL) {
  275.         return;
  276.     }
  277.     hPtr = Tcl_FindHashEntry(hTblPtr, (char *) acceptCallbackPtr);
  278.     if (hPtr == (Tcl_HashEntry *) NULL) {
  279.         return;
  280.     }
  281.     Tcl_DeleteHashEntry(hPtr);
  282. }
  283.  
  284.  
  285.         /* ARGSUSED */
  286. static int
  287. PisockCloseProc(instanceData, interp)
  288.     ClientData instanceData;    /* The socket to close. */
  289.     Tcl_Interp *interp;         /* For error reporting - unused. */
  290. {
  291.     PisockState *statePtr = (PisockState *) instanceData;
  292.     int errorCode = 0;
  293.  
  294.     /*
  295.      * Delete a file handler that may be active for this socket if this
  296.      * is a server socket - the file handler was created automatically
  297.      * by Tcl as part of the mechanism to accept new client connections.
  298.      * Channel handlers are already deleted in the generic IO channel
  299.      * closing code that called this function, so we do not have to
  300.      * delete them here.
  301.      */
  302.  
  303.     Tcl_DeleteFileHandler(statePtr_fd);
  304.  
  305.     if (pi_close(statePtr->fd) < 0) {
  306.         errorCode = errno;
  307.     }
  308.     ckfree((char *) statePtr);
  309.  
  310.     return errorCode;
  311. }
  312.  
  313.         /* ARGSUSED */
  314. static int
  315. PisockInputProc(instanceData, buf, bufSize, errorCodePtr)
  316.     ClientData instanceData;            /* Socket state. */
  317.     char *buf;                          /* Where to store data read. */
  318.     int bufSize;                        /* How much space is available
  319.                                          * in the buffer? */
  320.     int *errorCodePtr;                  /* Where to store error code. */
  321. {
  322.     PisockState *statePtr = (PisockState *) instanceData;
  323.     int bytesRead, state;
  324.  
  325.     *errorCodePtr = 0;
  326.     state = WaitForConnect(statePtr, errorCodePtr);
  327.     if (state != 0) {
  328.         return -1;
  329.     }
  330.     bytesRead = pi_recv(statePtr->fd, buf, bufSize, 0);
  331.     if (bytesRead > -1) {
  332.         return bytesRead;
  333.     }
  334.     if (errno == ECONNRESET) {
  335.  
  336.         /*
  337.          * Turn ECONNRESET into a soft EOF condition.
  338.          */
  339.  
  340.         return 0;
  341.     }
  342.     *errorCodePtr = errno;
  343.     return -1;
  344. }
  345.  
  346. static int
  347. PisockOutputProc(instanceData, buf, toWrite, errorCodePtr)
  348.     ClientData instanceData;            /* Socket state. */
  349.     char *buf;                          /* The data buffer. */
  350.     int toWrite;                        /* How many bytes to write? */
  351.     int *errorCodePtr;                  /* Where to store error code. */
  352. {
  353.     PisockState *statePtr = (PisockState *) instanceData;
  354.     int written;
  355.     int state;                          /* Of waiting for connection. */
  356.  
  357.     *errorCodePtr = 0;
  358.     state = WaitForConnect(statePtr, errorCodePtr);
  359.     if (state != 0) {
  360.         return -1;
  361.     }
  362.     written = pi_send(statePtr->fd, buf, toWrite, 0);
  363.     if (written > -1) {
  364.         return written;
  365.     }
  366.     *errorCodePtr = errno;
  367.     return -1;
  368. }
  369.  
  370. static void
  371. PisockWatchProc(instanceData, mask)
  372.     ClientData instanceData;            /* The socket state. */
  373.     int mask;                           /* Events of interest; an OR-ed
  374.                                          * combination of TCL_READABLE,
  375.                                          * TCL_WRITABLE and TCL_EXCEPTION. */
  376. {
  377.     PisockState *statePtr = (PisockState *) instanceData;
  378.  
  379. #if TCL_MAJOR_VERSION >=8
  380.     if (mask) {
  381.         Tcl_CreateFileHandler(statePtr_fd, mask,
  382.                 (Tcl_FileProc *) Tcl_NotifyChannel,
  383.                 (ClientData) statePtr->channel);
  384.     } else {
  385.         Tcl_DeleteFileHandler(statePtr_fd);
  386.     }
  387. #else
  388.     Tcl_WatchFile(Tcl_GetFile((ClientData)statePtr->fd, TCL_UNIX_FD), mask);
  389. #endif
  390.         
  391. }
  392.  
  393. #if TCL_MAJOR_VERSION >= 8
  394.         /* ARGSUSED */
  395. static int
  396. PisockGetHandleProc(instanceData, direction, handlePtr)
  397.     ClientData instanceData;    /* The socket state. */
  398.     int direction;              /* Not used. */
  399.     ClientData *handlePtr;      /* Where to store the handle.  */
  400. {
  401.     PisockState *statePtr = (PisockState *) instanceData;
  402.  
  403.     *handlePtr = (ClientData)statePtr->fd;
  404.     return TCL_OK;
  405. }
  406. #else
  407.         /* ARGSUSED */
  408. static Tcl_File
  409. OldPisockGetHandleProc(instanceData, direction)
  410.     ClientData instanceData;    /* The socket state. */
  411.     int direction;              /* Not used. */
  412. {
  413.     PisockState *statePtr = (PisockState *) instanceData;
  414.  
  415.     return Tcl_GetFile((ClientData)statePtr->fd, TCL_UNIX_FD);
  416. }
  417.  
  418. static int
  419. PisockReadyProc(instanceData, mask)
  420. ClientData instanceData;
  421. int mask;
  422. {
  423.     PisockState *statePtr = (PisockState *) instanceData;
  424.         
  425.     return Tcl_FileReady(Tcl_GetFile((ClientData)statePtr->fd, TCL_UNIX_FD), mask);
  426. }
  427.  
  428. #endif
  429.  
  430. static int
  431. WaitForConnect(statePtr, errorCodePtr)
  432.     PisockState *statePtr;         /* State of the socket. */
  433.     int *errorCodePtr;          /* Where to store errors? */
  434. {
  435. #if 0
  436.     int timeOut;                /* How long to wait. */
  437.     int state;                  /* Of calling TclWaitForFile. */
  438.     int flags;                  /* fcntl flags for the socket. */
  439.  
  440.     /*
  441.      * If an asynchronous connect is in progress, attempt to wait for it
  442.      * to complete before reading.
  443.      */
  444.  
  445.     if (statePtr->flags & TCP_ASYNC_CONNECT) {
  446.         if (statePtr->flags & TCP_ASYNC_SOCKET) {
  447.             timeOut = 0;
  448.         } else {
  449.             timeOut = -1;
  450.         }
  451.         errno = 0;
  452.         state = TclUnixWaitForFile(statePtr->fd,
  453.                 TCL_WRITABLE | TCL_EXCEPTION, timeOut);
  454.         if (!(statePtr->flags & TCP_ASYNC_SOCKET)) {
  455. #ifndef USE_FIONBIO
  456.             flags = fcntl(statePtr->fd, F_GETFL);
  457.             flags &= (~(O_NONBLOCK));
  458.             (void) fcntl(statePtr->fd, F_SETFL, flags);
  459. #endif
  460.  
  461. #ifdef  USE_FIONBIO
  462.             flags = 0;
  463.             (void) ioctl(statePtr->fd, FIONBIO, &flags);
  464. #endif
  465.         }
  466.         if (state & TCL_EXCEPTION) {
  467.             return -1;
  468.         }
  469.         if (state & TCL_WRITABLE) {
  470.             statePtr->flags &= (~(TCP_ASYNC_CONNECT));
  471.         } else if (timeOut == 0) {
  472.             *errorCodePtr = errno = EWOULDBLOCK;
  473.             return -1;
  474.         }
  475.     }
  476. #endif
  477.     return 0;
  478. }
  479.  
  480. static void
  481. AcceptCallbackProc(callbackData, chan)
  482.     ClientData callbackData;            /* The data stored when the callback
  483.                                          * was created in the call to
  484.                                          * Tcl_OpenTcpServer. */
  485.     Tcl_Channel chan;                   /* Channel for the newly accepted
  486.                                          * connection. */
  487. {
  488.     AcceptCallback *acceptCallbackPtr;
  489.     Tcl_Interp *interp;
  490.     char *script;
  491.     int result;
  492.  
  493.     acceptCallbackPtr = (AcceptCallback *) callbackData;
  494.  
  495.     /*
  496.      * Check if the callback is still valid; the interpreter may have gone
  497.      * away, this is signalled by setting the interp field of the callback
  498.      * data to NULL.
  499.      */
  500.  
  501.     if (acceptCallbackPtr->interp != (Tcl_Interp *) NULL) {
  502.  
  503.         script = acceptCallbackPtr->script;
  504.         interp = acceptCallbackPtr->interp;
  505.  
  506.         Tcl_Preserve((ClientData) script);
  507.         Tcl_Preserve((ClientData) interp);
  508.  
  509.         Tcl_RegisterChannel(interp, chan);
  510.         result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan),
  511.                 (char *) NULL);
  512.         if (result != TCL_OK) {
  513.             Tcl_BackgroundError(interp);
  514.             Tcl_UnregisterChannel(interp, chan);
  515.         }
  516.         Tcl_Release((ClientData) interp);
  517.         Tcl_Release((ClientData) script);
  518.     } else {
  519.  
  520.         /*
  521.          * The interpreter has been deleted, so there is no useful
  522.          * way to utilize the client socket - just close it.
  523.          */
  524.  
  525.         Tcl_Close((Tcl_Interp *) NULL, chan);
  526.     }
  527. }
  528.  
  529. static void
  530. PisockServerCloseProc(callbackData)
  531.     ClientData callbackData;    /* The data passed in the call to
  532.                                  * Tcl_CreateCloseHandler. */
  533. {
  534.     AcceptCallback *acceptCallbackPtr;
  535.                                 /* The actual data. */
  536.  
  537.     acceptCallbackPtr = (AcceptCallback *) callbackData;
  538.     if (acceptCallbackPtr->interp != (Tcl_Interp *) NULL) {
  539.         UnregisterPisockServerInterpCleanupProc(acceptCallbackPtr->interp,
  540.                 acceptCallbackPtr);
  541.     }
  542.     Tcl_EventuallyFree((ClientData) acceptCallbackPtr->script, TCL_DYNAMIC);
  543.     ckfree((char *) acceptCallbackPtr);
  544. }
  545.  
  546.  
  547. static void
  548. PisockAccept(data, mask)
  549.     ClientData data;                    /* Callback token. */
  550.     int mask;                           /* Not used. */
  551. {
  552.     PisockState *sockState;                /* Client data of server socket. */
  553.     int newsock;                        /* The new client socket */
  554.     PisockState *newSockState;             /* State for new socket. */
  555.     /*int len;*/                            /* For accept interface */
  556.     char channelName[20];
  557.  
  558.     sockState = (PisockState *) data;
  559.  
  560.     newsock = pi_accept(sockState->fd, 0, 0);
  561.     if (newsock < 0) {
  562.         return;
  563.     }
  564.     register_sock(newsock);
  565.  
  566.     /*
  567.      * Set close-on-exec flag to prevent the newly accepted socket from
  568.      * being inherited by child processes.
  569.      */
  570.  
  571.     /*(void) fcntl(newsock, F_SETFD, FD_CLOEXEC);*/
  572.  
  573.     newSockState = (PisockState *) ckalloc((unsigned) sizeof(PisockState));
  574.  
  575.     newSockState->flags = 0;
  576.     newSockState->fd = newsock;
  577.     newSockState->acceptProc = (Tcl_PisockAcceptProc *) NULL;
  578.     newSockState->acceptProcData = (ClientData) NULL;
  579.  
  580.     sprintf(channelName, "pisock%d", newsock);
  581.     newSockState->channel = Tcl_CreateChannel(&pisockChannelType, channelName,
  582.             (ClientData) newSockState, (TCL_READABLE | TCL_WRITABLE));
  583.  
  584.     /*Tcl_SetChannelOption((Tcl_Interp *) NULL, newSockState->channel,
  585.             "-translation", "auto crlf");*/
  586.  
  587.     if (sockState->acceptProc != (Tcl_PisockAcceptProc *) NULL) {
  588.         (sockState->acceptProc) (sockState->acceptProcData,
  589.                 newSockState->channel);
  590.     }
  591. }
  592.  
  593.  
  594. #ifdef Objects
  595. static long tcl_enumobj(Tcl_Interp *interp, Tcl_Obj *object, struct tcl_e * e)
  596. {
  597.     int i;
  598.     long result;
  599.     char * str = Tcl_GetStringFromObj(object, 0);
  600.     for(i=0;e[i].name;i++) {
  601.         if (strcmp(e[i].name, str)==0)
  602.             return e[i].value;
  603.     }
  604.     result = 0;
  605.     Tcl_GetLongFromObj(interp, object, &result);
  606.     return result;
  607. }
  608. #endif
  609.  
  610. static int tcl_enum(Tcl_Interp *interp, char *str, struct tcl_e * e)
  611. {
  612.     int i;
  613.     int result;
  614.     for(i=0;e[i].name;i++) {
  615.         if (strcmp(e[i].name, str)==0)
  616.             return e[i].value;
  617.     }
  618.     result = 0;
  619.     Tcl_GetInt(interp, str, &result);
  620.     return result;
  621. }
  622.  
  623. #ifdef Objects
  624. static int tcl_socketobj(Tcl_Interp *interp, Tcl_Obj *object)
  625. {
  626.     int fd= 0;
  627.     Tcl_Channel c = Tcl_GetChannel(interp, Tcl_GetStringFromObj(object,0), 0);
  628.     if (!c) {
  629.         Tcl_GetIntFromObj(interp, object, &fd);
  630.     } else {
  631.         Tcl_GetChannelHandle(c, TCL_WRITABLE, (ClientData)&fd);
  632.     }
  633.     return fd;
  634. }
  635. #endif
  636.  
  637. static int tcl_socket(Tcl_Interp *interp, char * arg)
  638. {
  639.     int fd= 0;
  640.     Tcl_Channel c = Tcl_GetChannel(interp, arg, 0);
  641.     if (!c) {
  642.         Tcl_GetInt(interp, arg, &fd);
  643.     } else {
  644. #if TCL_MAJOR_VERSION >= 8
  645.         Tcl_GetChannelHandle(c, TCL_WRITABLE, (ClientData)&fd);
  646. #else
  647.         return (int)Tcl_GetFileInfo(Tcl_GetChannelFile(c, TCL_WRITABLE), 0);
  648. #endif
  649.     }
  650.     return fd;
  651. }
  652.  
  653. PisockState *
  654. CreateSocket(Tcl_Interp * interp, int protocol, char * remote, int server)
  655. {
  656.     PisockState *statePtr;
  657.     
  658.     int result;
  659.     int sock;
  660.     int type;
  661.     int domain = PI_AF_SLP;
  662.     struct pi_sockaddr * addr = 0;
  663.     int alen = 0;
  664.     
  665.     statePtr = (PisockState *) ckalloc((unsigned) sizeof(PisockState));
  666.     statePtr->flags = 0;
  667.  
  668.     if (protocol == PI_PF_SLP) 
  669.         type = PI_SOCK_RAW;
  670.     else
  671.         type = PI_SOCK_STREAM;
  672.     
  673.     sock = pi_socket(domain, type, protocol);
  674.     printf("Called pi_socket\n");
  675.     
  676.     register_sock(sock);
  677.  
  678.     statePtr->fd = sock;
  679.  
  680.     if (domain == PI_AF_SLP) {
  681.         char * device;
  682.         device = remote;
  683.         alen = strlen(device)+1+4;
  684.         addr = (struct pi_sockaddr*)malloc(alen);
  685.         strcpy(addr->pi_device, device);
  686.         addr->pi_family = PI_AF_SLP;
  687.     }
  688.     printf("addr = %ld\n", (long)addr);
  689.  
  690.     if (server) {
  691.         result = pi_bind(sock, (struct sockaddr*)addr, alen);
  692.         pi_listen(sock, 1);
  693.     } else {
  694.       result = pi_connect(sock, (struct sockaddr*)addr, alen);
  695.     }
  696.     printf(" result = %d\n", result);
  697.  
  698.    return statePtr;
  699. }
  700.  
  701. static Tcl_Channel
  702. ClientSocket(Tcl_Interp * interp, int protocol, char * remote)
  703. {
  704.     PisockState *statePtr;
  705.     
  706.     char channelName[20];
  707.     
  708.     statePtr = CreateSocket(interp, protocol, remote, 0);
  709.    if (statePtr == NULL) {
  710.         return NULL;
  711.    }
  712.    printf("Created socket\n");
  713.                 
  714.     statePtr->acceptProc = NULL;
  715.     statePtr->acceptProcData = (ClientData) NULL;
  716.  
  717.     sprintf(channelName, "pisock%d", statePtr->fd);
  718.     statePtr->channel = Tcl_CreateChannel(&pisockChannelType, channelName,
  719.                 (ClientData) statePtr, (TCL_READABLE|TCL_WRITABLE));
  720.     return statePtr->channel;
  721. }
  722.  
  723. static Tcl_Channel
  724. ServerSocket(Tcl_Interp * interp, int protocol, char * remote,
  725.     Tcl_PisockAcceptProc *acceptProc, ClientData acceptProcData)
  726. {
  727.     PisockState *statePtr;
  728.     
  729.     char channelName[20];
  730.     
  731.     statePtr = CreateSocket(interp, protocol, remote, 1);
  732.    if (statePtr == NULL) {
  733.         return NULL;
  734.    }
  735.    printf("Server: Created socket\n");
  736.                 
  737.     statePtr->acceptProc = acceptProc;
  738.     statePtr->acceptProcData = (ClientData)acceptProcData;
  739.     
  740.    Tcl_CreateFileHandler(statePtr_fd, TCL_READABLE, PisockAccept,
  741.            (ClientData) statePtr);
  742.  
  743.     sprintf(channelName, "pisock%d", statePtr->fd);
  744.     statePtr->channel = Tcl_CreateChannel(&pisockChannelType, channelName,
  745.                 (ClientData) statePtr, 0);
  746.     
  747.     printf("Competed bounding\n");
  748.     return statePtr->channel;
  749. }
  750.  
  751. int
  752. OpenSocketCmd(notUsed, interp, argc, argv)
  753.     ClientData notUsed;            /* Not used. */
  754.     Tcl_Interp *interp;            /* Current interpreter. */
  755.     int argc;                /* Number of arguments. */
  756.     char **argv;            /* Argument strings. */
  757. {
  758.     int a, server;
  759.     char *arg, *copyScript, *host, *script;
  760.     int protocol = PI_PF_PADP;
  761.     int async = 0;
  762.     Tcl_Channel chan;
  763.     AcceptCallback *acceptCallbackPtr;
  764.     
  765.     server = 0;
  766.     script = NULL;
  767.  
  768.     for (a = 1; a < argc; a++) {
  769.         arg = argv[a];
  770.         if (arg[0] == '-') {
  771.             if (strcmp(arg, "-server") == 0) {
  772.              if (async == 1) {
  773.                 Tcl_AppendResult(interp,
  774.                             "cannot set -async option for server sockets",
  775.                             (char *) NULL);
  776.                     return TCL_ERROR;
  777.                 }
  778.         server = 1;
  779.         a++;
  780.         if (a >= argc) {
  781.             Tcl_AppendResult(interp,
  782.                 "no argument given for -server option",
  783.                             (char *) NULL);
  784.             return TCL_ERROR;
  785.         }
  786.                 script = argv[a];
  787.             }  else if (strcmp(arg, "-myprotocol") == 0) {
  788.         a++;
  789.                 if (a >= argc) {
  790.             Tcl_AppendResult(interp,
  791.                 "no argument given for -myprotocol option",
  792.                             (char *) NULL);
  793.             return TCL_ERROR;
  794.         }
  795.         protocol = atoi(argv[a]);
  796.             }/*else if (strcmp(arg, "-async") == 0) {
  797.                 if (server == 1) {
  798.                     Tcl_AppendResult(interp,
  799.                             "cannot set -async option for server sockets",
  800.                             (char *) NULL);
  801.                     return TCL_ERROR;
  802.                 }
  803.                 async = 1;
  804.         }*/ else {
  805.         Tcl_AppendResult(interp, "bad option \"", arg,
  806.                         "\", must be -myprotocol or -server",
  807.                         (char *) NULL);
  808.         return TCL_ERROR;
  809.         }
  810.     } else {
  811.         break;
  812.     }
  813.     }
  814. #if 0
  815.     if (server) {
  816.         host = myaddr;        /* NULL implies INADDR_ANY */
  817.     if (myport != 0) {
  818.         Tcl_AppendResult(interp, "Option -myport is not valid for servers",
  819.             NULL);
  820.         return TCL_ERROR;
  821.     }
  822.     } else 
  823. #endif
  824.     if (a < argc) {
  825.     host = argv[a];
  826.     a++;
  827.     } else {
  828. /*wrongNumArgs:*/
  829.     Tcl_AppendResult(interp, "wrong # args: should be either:\n",
  830.         argv[0],
  831.                 " ?-myprotocol protocol? ?-async? host\n",
  832.         argv[0],
  833.                 " -server command ?-myprotocol protocol? host",
  834.                 (char *) NULL);
  835.         return TCL_ERROR;
  836.     }
  837.  
  838.     if (server) {
  839.         acceptCallbackPtr = (AcceptCallback *) ckalloc((unsigned)
  840.                 sizeof(AcceptCallback));
  841.         copyScript = ckalloc((unsigned) strlen(script) + 1);
  842.         strcpy(copyScript, script);
  843.         acceptCallbackPtr->script = copyScript;
  844.         acceptCallbackPtr->interp = interp;
  845.         chan = ServerSocket(interp, protocol, host, AcceptCallbackProc,
  846.                 (ClientData) acceptCallbackPtr);
  847.         if (chan == (Tcl_Channel) NULL) {
  848.             ckfree(copyScript);
  849.             ckfree((char *) acceptCallbackPtr);
  850.             return TCL_ERROR;
  851.         }
  852.  
  853.         /*
  854.          * Register with the interpreter to let us know when the
  855.          * interpreter is deleted (by having the callback set the
  856.          * acceptCallbackPtr->interp field to NULL). This is to
  857.          * avoid trying to eval the script in a deleted interpreter.
  858.          */
  859.  
  860.         RegisterPisockServerInterpCleanup(interp, acceptCallbackPtr);
  861.         
  862.         /*
  863.          * Register a close callback. This callback will inform the
  864.          * interpreter (if it still exists) that this channel does not
  865.          * need to be informed when the interpreter is deleted.
  866.          */
  867.         
  868.         Tcl_CreateCloseHandler(chan, PisockServerCloseProc,
  869.                 (ClientData) acceptCallbackPtr);
  870.     } else {
  871.             printf("Protocol = %d, host = '%s'\n", protocol, host);
  872.         chan = ClientSocket(interp, protocol, host);
  873.         if (chan == (Tcl_Channel) NULL) {
  874.             return TCL_ERROR;
  875.         }
  876.         printf("got channel!\n");
  877.     }
  878.     Tcl_RegisterChannel(interp, chan);            
  879.     Tcl_AppendResult(interp, Tcl_GetChannelName(chan), (char *) NULL);
  880.     
  881.     return TCL_OK;
  882. }
  883.  
  884. static int
  885. socketCmd(ClientData clientData, Tcl_Interp * interp, int argc, char * argv[])
  886. {
  887.     PisockState *statePtr;
  888.     
  889.     int result;
  890.     int x,y,z;
  891.     char channelName[40];
  892.     if (argc != 4) {
  893.         Tcl_SetResult(interp, "Usage: x, y, z", TCL_STATIC);
  894.         return TCL_ERROR;
  895.     }
  896.     
  897.     x = tcl_enum(interp, argv[1], domains);
  898.     y = tcl_enum(interp, argv[2], types);
  899.     z = tcl_enum(interp, argv[3], protocols);
  900.     
  901.     result = pi_socket(x,y,z);
  902.     
  903.     register_sock(result);
  904.  
  905.     statePtr = (PisockState *) ckalloc((unsigned) sizeof(PisockState));
  906.     statePtr->flags = 0;
  907.     statePtr->fd = result;
  908.  
  909.     /*statePtr = CreateSocket(interp, port, host, 0, myaddr, myport, async);
  910.     if (statePtr == NULL) {
  911.         return NULL;
  912.     }*/
  913.  
  914.     /*statePtr->acceptProc = NULL;
  915.     statePtr->acceptProcData = (ClientData) NULL;
  916.     Tcl_CreateFileHandler(statePtr->fd, TCL_READABLE, TcpAccept,
  917.             (ClientData) statePtr);*/
  918.  
  919.     sprintf(channelName, "pisock%d", statePtr->fd);
  920.  
  921.     statePtr->channel = Tcl_CreateChannel(&pisockChannelType, channelName,
  922.             (ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));
  923.         
  924.     /*return statePtr;*/
  925.  
  926.     Tcl_RegisterChannel(interp, statePtr->channel);
  927.     Tcl_AppendResult(interp, Tcl_GetChannelName(statePtr->channel), (char *) NULL);
  928.     return TCL_OK;
  929. /*            
  930.     
  931.     if (result == -1) {
  932.         Tcl_SetResult(interp, Tcl_PosixError(interp), TCL_STATIC);
  933.         return TCL_ERROR;
  934.     }
  935.     else {
  936.         Tcl_SetIntObj(Tcl_GetObjResult(interp), result);
  937.         return TCL_OK;
  938.     }*/
  939. }
  940.  
  941. static int
  942. bindCmd(ClientData clientData, Tcl_Interp * interp, int argc, char * argv[])
  943. {
  944.     int result;
  945.     int s;
  946.     int family;
  947.     char * device;
  948.     struct pi_sockaddr * addr = 0;
  949.     int alen = 0;
  950.     if (argc != 4) {
  951.         Tcl_SetResult(interp, "Usage: socket family device", TCL_STATIC);
  952.         return TCL_ERROR;
  953.     }
  954.     
  955.     Tcl_GetInt(interp, argv[1], &s);
  956.     family = tcl_enum(interp, argv[2], domains);
  957.     
  958.     if (family == PI_AF_SLP) {
  959.         device = argv[3];
  960.         alen = strlen(device)+1+4;
  961.         addr = (struct pi_sockaddr*)malloc(alen);
  962.         strcpy(addr->pi_device, device);
  963.         addr->pi_family = family;
  964.     }
  965.     
  966.     result = pi_bind(s, (struct sockaddr*)addr, alen);
  967.     
  968.     if (addr)
  969.         free(addr);
  970.     
  971.     if (result == -1) {
  972.         Tcl_SetResult(interp, Tcl_PosixError(interp), TCL_STATIC);
  973.         return TCL_ERROR;
  974.     }
  975.     else {
  976.         Tcl_AppendInt(interp, result);
  977.         return TCL_OK;
  978.     }
  979. }
  980.  
  981. static int
  982. OpenConduitCmd(ClientData clientData, Tcl_Interp * interp, int argc, char *argv[])
  983. {
  984.     if (argc != 2) {
  985.         Tcl_SetResult(interp, "Usage: Status socket", TCL_STATIC);
  986.         return TCL_ERROR;
  987.     }
  988.     dlp_OpenConduit(tcl_socket(interp, argv[1]));
  989.     return TCL_OK;
  990. }
  991.  
  992. int invalid_socket(Tcl_Interp*interp, int sock)
  993. {
  994.     if ((sock < 0) || (sock >= packers) || (pi_version(sock)==-1)) {
  995.         Tcl_SetResult(interp, "Invalid socket", TCL_STATIC);
  996.         return 1;
  997.     }
  998.     return 0;
  999. }
  1000.  
  1001. static int
  1002. OpenDBCmd(ClientData clientData, Tcl_Interp * interp, int argc, char*argv[])
  1003. {
  1004.     int result;
  1005.     int handle;
  1006.     int cardno=0,mode=0x80|0x40;
  1007.     int sock;
  1008.     int i;
  1009.     char * name;
  1010.     if ((argc < 3 )|| (argc > 5)) {
  1011.         Tcl_SetResult(interp, "Usage: Open socket name [card [mode]]", TCL_STATIC);
  1012.         return TCL_ERROR;
  1013.     }
  1014.     if (argc>=3)
  1015.         Tcl_GetInt(interp, argv[3], &cardno);
  1016.     if (argc>=4) {
  1017.         char * modestr = argv[4];
  1018.         mode = 0;
  1019.         if (strchr(modestr, 'S') || strchr(modestr,'s'))
  1020.             mode |= dlpOpenSecret;
  1021.         if (strchr(modestr, 'E') || strchr(modestr,'e'))
  1022.             mode |= dlpOpenExclusive;
  1023.         if (strchr(modestr, 'W') || strchr(modestr,'w'))
  1024.             mode |= dlpOpenWrite;
  1025.         if (strchr(modestr, 'R') || strchr(modestr,'r'))
  1026.             mode |= dlpOpenRead;
  1027.     }
  1028.     name = argv[2];
  1029.     sock = tcl_socket(interp, argv[1]);
  1030.     if (invalid_socket(interp, sock))
  1031.         return TCL_ERROR;
  1032.  
  1033.     result = dlp_OpenDB(sock, cardno, mode, name, &handle);
  1034.     printf("Result = %d, name = '%s', mode = %x, card = %d, handle = %d\n", 
  1035.         result, name, mode, cardno, handle);
  1036.  
  1037.     if (result<0) {
  1038.         Tcl_SetResult(interp, dlp_strerror(result), TCL_STATIC);
  1039.         return TCL_ERROR;
  1040.     }
  1041.  
  1042.     for(i=0; DBPackers[i].name && strcmp(DBPackers[i].name, name); i++)
  1043.         ;
  1044.  
  1045.     memset(&pack[sock], 0, sizeof(struct Packer));
  1046.     
  1047.     if (DBPackers[i].name) {
  1048.         pack[sock].name = DBPackers[i].name;
  1049.         pack[sock].pack = DBPackers[i].pack;
  1050.         pack[sock].unpack = DBPackers[i].unpack;
  1051.         pack[sock].packai = DBPackers[i].packai;
  1052.         pack[sock].unpackai = DBPackers[i].unpackai;
  1053.         pack[sock].packsi = DBPackers[i].packsi;
  1054.         pack[sock].unpacksi = DBPackers[i].unpacksi;
  1055.     }
  1056.     
  1057.     Tcl_AppendInt(interp, handle);
  1058.     return TCL_OK;
  1059. }
  1060.  
  1061. #ifdef Objects
  1062. Tcl_Obj *
  1063. InvokeFunc(Tcl_Interp * interp, Tcl_Obj * cmd, Tcl_Obj * record)
  1064. {
  1065.     Tcl_Obj * l = Tcl_NewListObj(0,0);
  1066.     int err;
  1067.     Tcl_ListObjAppendElement(interp, l, cmd);
  1068.     Tcl_ListObjAppendElement(interp, l, record);
  1069.     
  1070.     err = Tcl_EvalObj(interp, l);
  1071.     Tcl_DecrRefCount(l);
  1072.     if (err != TCL_OK)
  1073.         return 0;
  1074.     
  1075.     l = Tcl_GetObjResult(interp);
  1076.     Tcl_IncrRefCount(l);
  1077.     return l;
  1078. }
  1079. #endif
  1080.  
  1081. static int
  1082. GetRecordCmd(ClientData clientData, Tcl_Interp * interp, int argc, char *argv[])
  1083. {
  1084.     int result;
  1085.     int handle;
  1086.     int index;
  1087.     int sock;
  1088.     int len,attr,cat;
  1089.     recordid_t id;
  1090.     
  1091.     if (argc != 4 ) {
  1092.         Tcl_SetResult(interp, "Usage: GetRecord socket dbhandle index", TCL_STATIC);
  1093.         return TCL_ERROR;
  1094.     }
  1095.     
  1096.     Tcl_GetInt(interp, argv[3], &index);
  1097.     Tcl_GetInt(interp, argv[2], &handle);
  1098.     
  1099.     sock = tcl_socket(interp, argv[1]);
  1100.     if (invalid_socket(interp, sock))
  1101.         return TCL_ERROR;
  1102.     if (!pack[sock].unpack) {
  1103.         Tcl_SetResult(interp, "An unpacker must be defined", TCL_STATIC);
  1104.         return TCL_ERROR;
  1105.     }
  1106.     
  1107.     result = dlp_ReadRecordByIndex(tcl_socket(interp, argv[1]), handle, index, buf, &id, &len, &attr, &cat);
  1108.     
  1109.     if (result<0) {
  1110.         Tcl_SetResult(interp, dlp_strerror(result), TCL_STATIC);
  1111.         return TCL_ERROR;
  1112.     }
  1113.     
  1114.     pack[sock].unpack(interp, buf, len);
  1115.     Tcl_AppendInt(interp, index);
  1116.     Tcl_AppendInt(interp, id);
  1117.     Tcl_AppendInt(interp, attr);
  1118.     Tcl_AppendInt(interp, cat);
  1119.  
  1120.     return TCL_OK;
  1121. }
  1122.  
  1123. static int
  1124. SetRecordCmd(ClientData clientData, Tcl_Interp * interp, int argc, char *argv[])
  1125. {
  1126.     int result;
  1127.     int handle;
  1128.     int index;
  1129.     int sock;
  1130.     int len,attr,cat;
  1131.     recordid_t id;
  1132.     
  1133.     if (argc != 7 ) {
  1134.         Tcl_SetResult(interp, "Usage: SetRecord socket dbhandle record id attr cat", TCL_STATIC);
  1135.         return TCL_ERROR;
  1136.     }
  1137.     
  1138.     Tcl_GetInt(interp, argv[2], &handle);
  1139.     
  1140.     sock = tcl_socket(interp, argv[1]);
  1141.     if (invalid_socket(interp, sock))
  1142.         return TCL_ERROR;
  1143.     if (!pack[sock].pack) {
  1144.         Tcl_SetResult(interp, "An unpacker must be defined", TCL_STATIC);
  1145.         return TCL_ERROR;
  1146.     }
  1147.     
  1148.     Tcl_GetInt(interp, argv[4], &index); id = index;
  1149.     Tcl_GetInt(interp, argv[5], &attr);
  1150.     Tcl_GetInt(interp, argv[6], &cat);
  1151.  
  1152.     len = pack[sock].pack(interp, argv[3], buf, 0xffff);
  1153.     
  1154.     result = dlp_WriteRecord(sock, handle, attr, id, cat, buf, len, &id);
  1155.     
  1156.     free(buf);
  1157.     
  1158.     if (result<0) {
  1159.         Tcl_SetResult(interp, dlp_strerror(result), TCL_STATIC);
  1160.         return TCL_ERROR;
  1161.     }
  1162.     
  1163.     Tcl_AppendInt(interp, (int)id);
  1164.  
  1165.     return TCL_OK;
  1166. }
  1167.  
  1168. static int
  1169. AddSyncLogEntryCmd(ClientData clientData, Tcl_Interp * interp, int argc, char *argv[])
  1170. {
  1171.     if (argc != 3) {
  1172.         Tcl_SetResult(interp, "Usage: Log socket text", TCL_STATIC);
  1173.         return TCL_ERROR;
  1174.     }
  1175.     dlp_AddSyncLogEntry(tcl_socket(interp, argv[1]), argv[2]);
  1176.     return TCL_OK;
  1177. }
  1178.  
  1179. static int
  1180. PackersCmd(ClientData clientData, Tcl_Interp * interp, int argc, char *argv[])
  1181. {
  1182.     int sock;
  1183.     int i;
  1184.     if ((argc < 2) || (argc>3)) {
  1185.         Tcl_SetResult(interp, "Usage: Packers socket [-none|dbname]", TCL_STATIC);
  1186.         return TCL_ERROR;
  1187.     }
  1188.     
  1189.     sock = tcl_socket(interp, argv[1]);
  1190.     if (invalid_socket(interp, sock))
  1191.         return TCL_ERROR;
  1192.         
  1193.     if (argc==2) {
  1194.         Tcl_SetResult(interp, pack[sock].name ? pack[sock].name : "-none", TCL_STATIC);
  1195.         return TCL_OK;
  1196.     }
  1197.     
  1198.     memset(&pack[sock], 0, sizeof(struct Packer));
  1199.     
  1200.     if ((argc==3) && (argv[2][0] == '-') && (strcmp(argv[2], "-none")==0)) {
  1201.         pack[sock].name = "-none";
  1202.         return TCL_OK;
  1203.     }
  1204.     
  1205.     for(i=0; DBPackers[i].name && strcmp(DBPackers[i].name, argv[2]); i++)
  1206.         ;
  1207.  
  1208.     if (DBPackers[i].name) {
  1209.         pack[sock].name = DBPackers[i].name;
  1210.         pack[sock].pack = DBPackers[i].pack;
  1211.         pack[sock].unpack = DBPackers[i].unpack;
  1212.         pack[sock].packai = DBPackers[i].packai;
  1213.         pack[sock].unpackai = DBPackers[i].unpackai;
  1214.         pack[sock].packsi = DBPackers[i].packsi;
  1215.         pack[sock].unpacksi = DBPackers[i].unpacksi;
  1216.         return TCL_OK;
  1217.     }
  1218.     
  1219.     Tcl_SetResult(interp, "Unknown packer dbname", TCL_STATIC);
  1220.     return TCL_ERROR;
  1221. }
  1222.  
  1223.  
  1224. #ifdef Objects
  1225. static struct { char * name; Tcl_ObjCmdProc *proc; } oprocs[] = {
  1226.     {0,0}
  1227. };
  1228. #endif
  1229.  
  1230. static struct { char * name; Tcl_CmdProc *proc; } procs[] = {
  1231.     {"dlpOpen", OpenDBCmd},
  1232.     {"piOpen", OpenSocketCmd},
  1233.     {"dlpLog", AddSyncLogEntryCmd},
  1234.     {"dlpStatus", OpenConduitCmd},
  1235.     {"piSocket", socketCmd},
  1236.     {"piBind", bindCmd},
  1237.     {"dlpGetRecord", GetRecordCmd},
  1238.     {"dlpPackers", PackersCmd},
  1239.     {"dlpSetRecord", SetRecordCmd},
  1240.     {0,0}
  1241. };
  1242.  
  1243. int Pdapilot_Init(Tcl_Interp *interp) {
  1244.     int i;
  1245.     
  1246.     for(i=0;procs[i].name;i++) {
  1247.         Tcl_CreateCommand(interp, procs[i].name, procs[i].proc, 0, 0);
  1248.     }
  1249.  
  1250. #ifdef Objects
  1251.     for(i=0;oprocs[i].name;i++) {
  1252.         Tcl_CreateObjCommand(interp, oprocs[i].name, oprocs[i].proc, 0, 0);
  1253.     }
  1254. #endif
  1255.     
  1256.     Tcl_PkgProvide(interp, "Pdapilot", PACKAGE_VERSION);
  1257.  
  1258.     return TCL_OK;
  1259. }
  1260.